package cn.iocoder.yudao.module.pay.framework.impl.mallbook;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.RSA;
import cn.iocoder.yudao.framework.common.exception.Assertions;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.module.pay.framework.PayClientConfig;
import com.trhui.mallbook.common.rsa.RsaUtil;
import com.trhui.mallbook.domain.common.ApiResponse;
import jakarta.validation.Validator;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;

import java.util.Map;
import java.util.Objects;

/**
 * MallBook 聚合支付的 PayClientConfig 实现类
 *
 * @author 山野羡民
 * @since 2025/05/15
 */
@Data
public class MallBookPayClientConfig implements PayClientConfig {

    public static class Holder {
        public static final MallBookPayClientConfig INSTANCE = new MallBookPayClientConfig();
    }

    @NotBlank(message = "接口 baseUrl 不能为空")
    private String baseUrl;

    @NotBlank(message = "接口 publicKey 不能为空")
    private String publicKey;

    @NotBlank(message = "商户 privateKey 不能为空")
    private String merchantPrivateKey;

    @NotBlank(message = "平台商户号不能为空")
    private String merchantNo;

    @NotBlank(message = "平台商户用户编号的不能为空")
    private String merchantUserId;

    private MallBookPayClientConfig() {
        // TODO 先写死，后续再考虑改为后台配置
        this.baseUrl = "https://cloudpay.mallbook.cn/api";
        this.publicKey = """
                MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq6OLZKgUHH5wOk9xSBgN7yC17r3PQwMlY9/IorqrOlaIqrU0eAVZ5+dWrJD/3bdu7Ctq8n8trTm/IUYs7wtMg5SKwyX4/N+KQc2N7LL4yCq4vNl41q9sYgrtA0QnZoucIZcq1mwyu7RTDC8Wp7LGddnlkJsmL8masgMxA6cc9NwIDAQAB
                """;
        this.merchantPrivateKey = """
                MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMEztiWnXxVvKji62N8kMCgZ6ypBr1mWG/Tid0dJElHnhP36CqZm1FaGS04GRGcH1VegHCovsW1k2YyNeLzBwoCJmz1kose10I0RGy6qM3gPriDTrxBXo4vTfdc8NhUkpqVHjcTQzq7vwlLDXdcH91jkTHfzz1H6vsUoBHF+zSMFAgMBAAECgYANRxiFjfMi7fjg3TZ6X2pP1zgqN0ltxrs1ITtBUuxHZLnnGoAQ35BIQgJ64kNhMVCgLQjCfXScKAordq2Ni2NqgzLOVrNaqgts00PRCUNKOY4in+EWKhPWTQ3FH5iTA/U70ahPkDaRuKOhfKYR9MTvrQabI+3TigzIGInLkGd6AQJBAP48PUF5EUlQdNk9gurr8H/b4n4VhFfxRtHZMz+5aPRM16uKPx4sbQIdbwICJRnuJQWeGOVqlh61KSL52FSCCDECQQDCiwUNsgwOfBEEcpH+sUcsOFCisGS21FnfTwgr6EorVbk17LevjpheG3KEc9+xn3U8csuWS8FSsqNyhK5pUycVAkBeoHtISFCn0ht71EpLOEBOxr/5n/afaP2sE8TgfhlTfNp1TcKKb4yvUddEjxnSGfKLsbmggliX22QRUZ80bSWxAkAB7fMM4bkw45YfnytHhWaZT62tD2bQUWbayiPgm5swttbxa/meaiGkvUzzd1q+nkBBazoNsY6nTVJFrn80WDjJAkAIHM6qgWi7Y5j4gTvMVr8F1b+qja8DcushvMfhHVyioDSTD1/dKo0H6WIrSGHLkRCXNr6vHXFIHtGzd7fUmo8d
                """;
        this.merchantNo = "MBH25008";
        this.merchantUserId = "90122866043712";
    }

    @Override
    public void validate(Validator validator) {
        ValidationUtils.validate(validator, this);
    }

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;
        MallBookPayClientConfig that = (MallBookPayClientConfig) object;
        return Objects.equals(baseUrl, that.baseUrl) && Objects.equals(publicKey, that.publicKey) && Objects.equals(merchantPrivateKey, that.merchantPrivateKey) && Objects.equals(merchantNo, that.merchantNo) && Objects.equals(merchantUserId, that.merchantUserId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(baseUrl, publicKey, merchantPrivateKey, merchantNo, merchantUserId);
    }

    public String generateRequestNo() {
        return "MB" + System.currentTimeMillis() + RandomUtil.randomInt(1000, 9999);
    }

    public ApiResponse validateApiResponse(Map<String, String> params) {
        // {
        //    "date": "1752291592562",
        //    "msg": "操作成功",
        //    "result": "{\"amount\":\"990\",\"channelOrderId\":\"ZF1943877919714582529\",\"merOrderId\":\"UPY202507121139468918\",\"openid\":\"ojqDx62zefb6fseUu9yJzxCyujdk\",\"outTransId\":\"4200002763202507123985212265\",\"partyOrderId\":\"022125071241986354136371\",\"payFinishTime\":\"2025-07-12 11:39:52\",\"splitList\":[],\"status\":\"1\"}",
        //    "code": "0000",
        //    "sign": "aTssHhTwDl7Sy2rQlSKjE8DSjQz3wVXg5facJUAWbJRTWFt3mBMbBpCqYpaJ8ezVA6mzoN9eSkm2rdJPqL7uyCtjuQ4TGOdWWmsfU3bGwp2fi2q9a8sRx42c0IfYPMfbEhuUdRIA1GT/nmRO4z+EGQZKiA1yO7lQtWkVNZJafAM=",
        //    "version": "1.0.0"
        // }
        Assertions.notEmpty(params, "回调结果为空");
        ApiResponse response = new ApiResponse();
        response.setCode(MapUtil.getStr(params, "code"));
        response.setMsg(MapUtil.getStr(params, "msg"));
        response.setResult(MapUtil.getStr(params, "result"));
        response.setSign(MapUtil.getStr(params, "sign"));
        response.setDate(MapUtil.getStr(params, "date"));
        response.setVersion(MapUtil.getStr(params, "version"));
        // 验签，防止伪造通知
        boolean verify = RsaUtil.doCheck(response.toString(), response.getSign(), Holder.INSTANCE.getPublicKey());
        Assertions.isTrue(verify, "签名验证失败");
        return response;
    }


    // 注意：更换 RSA 秘钥对后须在 MallBook 平台商户管理控台的“系统管理/商户开发信息管理”同步更改
    public static void main(String[] args) {
        RSA rsa = SecureUtil.rsa();
        System.out.println("RSA 私钥：" + rsa.getPrivateKeyBase64());
        System.out.println("RSA 公钥：" + rsa.getPublicKeyBase64());
    }

}
